/*
	Model-View-Control

	游戏的各种状态与数据结构由 Model 管理
	View 用于显示 Model 的变化
	用户与游戏的交互由 Control 完成
	特点：Model完全独立，View 是 Model 的状态机，Model 与 View 都由 Control 来驱动。
*/

Array.prototype.deleteViewSnake = function(){   // 清除蛇之前的一节
	var aViewList = document.querySelectorAll('#view-wrap > div > div')
	aViewList[this[0] * 30 + this[1]].className = ''
}
Array.prototype.getZoneViewSnake = function(){  // 渲染画布上移动的蛇
	var aViewList = document.querySelectorAll('#view-wrap > div > div')
	this.map(function(a,b){
		aViewList[a[0] * 30 + a[1]].className = 'bodys'
	})	
	try{ // 蛇头转向 第一次拿不到Model 把错误抛出
		switch(Model.direction) {
			case '上':
				aViewList[this[this.length - 1][0] * 30 + this[this.length - 1][1]].className = 'head-top'
				break
			case '下':
				aViewList[this[this.length - 1][0] * 30 + this[this.length - 1][1]].className = 'head-bottom'
				break
			case '左':
				aViewList[this[this.length - 1][0] * 30 + this[this.length - 1][1]].className = 'head-left'
				break
			case '右':
				aViewList[this[this.length - 1][0] * 30 + this[this.length - 1][1]].className = 'head-right'
				break
		}
	}catch(err){

	}
}
Array.prototype.getZoneViewFoot = function(){   // 渲染食物
	var aViewList = document.querySelectorAll('#view-wrap > div > div')
	aViewList[ this[0] * 30 + this[1] ].className = 'eat'
}


Array.prototype.getLife = function(){  // 计算碰撞
	var life = true, _this = this
	if(this[this.length-1][0] > 29 || this[this.length-1][0] < 0 || this[this.length-1][1] > 29 || this[this.length-1][1] < 0){
		// 撞墙了
		document.querySelectorAll('#view-wrap > div > div')[this[this.length - 2][0] * 30 + this[this.length - 2][1]].innerHTML = '<b></b>'
		life = false
	}
	this.map(function(a,b){
		if(_this[_this.length-1][0] == a[0] && _this[_this.length-1][1] == a[1] && b != _this.length-1){
			// 撞自己
			document.querySelectorAll('#view-wrap > div > div')[_this[_this.length - 2][0] * 30 + _this[_this.length - 2][1]].innerHTML = '<b></b>'
			life = false
		}
	})
	return life
}



/*
	渲染视图 view
*/ 
var view = function(){
	this.directionArr = ['上','下','左','右']
	this.snake = [[parseInt(parseInt(Math.random( )*21+5)), parseInt(parseInt(Math.random( )*21+5))]] // 保持蛇头在5-25的矩阵
	this.setViewDom = function(x, y){
  		var oViewWrap = document.createElement('div')
  		oViewWrap.id = 'view-wrap'
  		for(var i = 0; i < x; i++){
  			var oListWrap = document.createElement('div')
	  		for(var j = 0; j < y; j++){
	  			oListWrap.appendChild(document.createElement('div'))
	  		} 
	  		oViewWrap.appendChild(oListWrap)		
  		}
  		document.getElementsByTagName('body')[0].appendChild(oViewWrap)
	}
	this.setSnake = function(){
		switch(this.directionArr[parseInt(Math.random( )*4)]) {
			case '上':
				this.snake.push([this.snake[this.snake.length-1][0] - 1, this.snake[this.snake.length-1][1]])
				break
			case '下':
				this.snake.push([this.snake[this.snake.length-1][0] + 1, this.snake[this.snake.length-1][1]])
				break
			case '左':
				this.snake.push([this.snake[this.snake.length-1][0], this.snake[this.snake.length-1][1] - 1])
				break
			case '右':
				this.snake.push([this.snake[this.snake.length-1][0], this.snake[this.snake.length-1][1] + 1])
				break
		}
		if(this.snake.length == 6){
			if(this.snake.getLife()){
				// 生成的蛇没有打结
				this.snake.getZoneViewSnake()
			}else{
				// 生成的蛇打结了
				document.querySelectorAll('#view-wrap > div > div')[this.snake[this.snake.length - 2][0] * 30 + this.snake[this.snake.length - 2][1]].innerHTML = ''
				this.snake.pop()
				this.setSnake()
			}	
		}else{
			if(this.snake.getLife()){
				// 生成的蛇没有打结
				this.setSnake()
			}else{
				// 生成的蛇打结了
				document.querySelectorAll('#view-wrap > div > div')[this.snake[this.snake.length - 2][0] * 30 + this.snake[this.snake.length - 2][1]].innerHTML = ''
				this.snake.pop()
				this.setSnake()
			}
		}
	}
	this.setFoot = function(){
		var _this = this
		this.foot = [parseInt(Math.random( )*30), parseInt(Math.random( )*30)]
		this.snake.map(function(a,b){
			if(_this.foot[0] == a[0] && _this.foot[1] == a[1]){ // 食物和蛇重叠
				_this.setFoot()
			}
		})
		this.foot.getZoneViewFoot()
	}
}

var View = new view()
View.setViewDom(30, 30) // 加载舞台dom结构
View.setSnake()         // 初始化生成蛇
View.setFoot()          // 初始化生成食物


/*
	游戏状态与数据结构 Model
*/
var model = function(){
	this.snake = View.snake  // 蛇
	this.direction = '右'  // 运动的方向 上下左右
	this.getDirection = function(){  // 初始运动方向非左即右
		if(this.snake[this.snake.length-1][0] == this.snake[this.snake.length-2][0] && this.snake[this.snake.length-1][1] + 1 == this.snake[this.snake.length-2][1]){
			this.direction = '左'
		}
	}
	this.move = function(){
		switch(this.direction) {
			case '上':
				this.snake.push([this.snake[this.snake.length-1][0] - 1, this.snake[this.snake.length-1][1]])
				break
			case '下':
				this.snake.push([this.snake[this.snake.length-1][0] + 1, this.snake[this.snake.length-1][1]])
				break
			case '左':
				this.snake.push([this.snake[this.snake.length-1][0], this.snake[this.snake.length-1][1] - 1])
				break
			case '右':
				this.snake.push([this.snake[this.snake.length-1][0], this.snake[this.snake.length-1][1] + 1])
				break
		}
		var a = this.snake.shift()
		 // 计算碰撞
		if( !this.snake.getLife() ){
			clearInterval(time)
			document.querySelectorAll('#over')[0].play() // 音效
			return false
			// 大结局
		}
		if(this.eatFoot()){
			// 吃到了
			this.snake.unshift(a)
			this.snake.getZoneViewSnake()
			document.querySelectorAll('#eat')[0].play()  // 音效
			View.setFoot() // 再生生一个食物
		}else{
			// 没吃到
			a.deleteViewSnake()
			this.snake.getZoneViewSnake()
		}
	}
	this.eatFoot = function(){
		if(this.snake[this.snake.length-1][0] == View.foot[0] && this.snake[this.snake.length-1][1] == View.foot[1]){
			// 吃到了
			return true
		}else{
			// 没吃到
			return false
		}
	}
}
var Model = new model()
	Model.getDirection()  // 计算初始运动方向
var time = setInterval(function(){
	Model.move() // 运动
},250)


/*
	事件交互控制器 Control
*/
var control = function(){
	window.onkeydown = function(evt){
		// 左37  上38  右39  下40
		switch(evt.keyCode) {
			case 37:
				if(Model.direction != '右'){
					Model.direction = '左'
				}
				break
			case 38:
				if(Model.direction != '下'){
					Model.direction = '上'
				}
				break
			case 39:
				if(Model.direction != '左'){
					Model.direction = '右'
				}
				break
			case 40:
				if(Model.direction != '上'){
					Model.direction = '下'
				}
				break
		}
	}
}
var Control = new control()